/**
 * @description 小程序专用错误处理器
 * @author 张一依有把越女剑
 * @date 2025-04-16
 */

// 简化的日志级别
const LOG_LEVELS = {
	DEBUG: 0,
	INFO: 1,
	WARN: 2,
	ERROR: 3
}

// 小程序专用日志管理器
class MiniprogramLogger {
	constructor() {
		this.level = LOG_LEVELS.INFO
		this.logs = []
		this.maxLogs = 500
	}
	
	setLevel(level) {
		this.level = level
	}
	
	log(level, message, data = null) {
		if (level < this.level) return
		
		const logEntry = {
			timestamp: new Date().toISOString(),
			level: Object.keys(LOG_LEVELS)[level],
			message,
			data
		}
		
		this.logs.push(logEntry)
		
		// 限制日志数量
		if (this.logs.length > this.maxLogs) {
			this.logs.shift()
		}
		
		// 控制台输出
		this.consoleOutput(logEntry)
		
		// 持久化存储
		this.persistLog(logEntry)
	}
	
	debug(message, data) {
		this.log(LOG_LEVELS.DEBUG, message, data)
	}
	
	info(message, data) {
		this.log(LOG_LEVELS.INFO, message, data)
	}
	
	warn(message, data) {
		this.log(LOG_LEVELS.WARN, message, data)
	}
	
	error(message, data) {
		this.log(LOG_LEVELS.ERROR, message, data)
	}
	
	consoleOutput(logEntry) {
		const { level, message, data } = logEntry
		
		if (data) {
			console.log(`[${level}] ${message}`, data)
		} else {
			console.log(`[${level}] ${message}`)
		}
	}
	
	persistLog(logEntry) {
		try {
			const storedLogs = uni.getStorageSync('app_logs') || []
			storedLogs.push(logEntry)
			
			// 只保留最近200条日志
			if (storedLogs.length > 200) {
				storedLogs.splice(0, storedLogs.length - 200)
			}
			
			uni.setStorageSync('app_logs', storedLogs)
		} catch (error) {
			console.error('Failed to persist log:', error)
		}
	}
	
	getLogs(level = null, limit = 100) {
		let filteredLogs = this.logs
		
		if (level !== null) {
			filteredLogs = this.logs.filter(log => log.level === level)
		}
		
		return filteredLogs.slice(-limit)
	}
	
	clearLogs() {
		this.logs = []
		try {
			uni.removeStorageSync('app_logs')
		} catch (error) {
			console.error('Failed to clear logs:', error)
		}
	}
}

// 小程序专用错误处理器
class MiniprogramErrorHandler {
	constructor() {
		this.errorCallbacks = []
		this.init()
	}
	
	init() {
		// 小程序全局错误监听
		if (typeof uni !== 'undefined') {
			uni.onError((error) => {
				this.handleError(error, 'Global Error')
			})
			
			uni.onUnhandledRejection((event) => {
				this.handleError(event.reason, 'Unhandled Promise Rejection')
			})
		}
	}
	
	handleError(error, context = 'Unknown') {
		try {
			const errorInfo = {
				message: error.message || error,
				stack: error.stack,
				context,
				timestamp: new Date().toISOString(),
				platform: this.getPlatformInfo()
			}
			
			// 记录错误日志
			logger.error(`${context}: ${errorInfo.message}`, errorInfo)
			
			// 执行错误回调
			this.errorCallbacks.forEach(callback => {
				try {
					callback(errorInfo)
				} catch (callbackError) {
					console.error('Error in error callback:', callbackError)
				}
			})
			
			// 用户友好的错误提示
			this.showUserFriendlyError(errorInfo)
		} catch (handlerError) {
			// 防止错误处理器本身出错导致无限循环
			console.error('Error in error handler:', handlerError)
		}
	}
	
	getPlatformInfo() {
		try {
			if (typeof uni !== 'undefined' && uni.getSystemInfoSync) {
				const systemInfo = uni.getSystemInfoSync()
				return `${systemInfo.platform} ${systemInfo.system} ${systemInfo.version}`
			}
			return 'Unknown Platform'
		} catch (error) {
			return 'Unknown Platform'
		}
	}
	
	showUserFriendlyError(errorInfo) {
		const friendlyMessages = {
			'Network Error': '网络连接异常，请检查网络设置',
			'Timeout': '请求超时，请稍后重试',
			'Permission denied': '权限不足，请联系管理员',
			'Storage quota exceeded': '存储空间不足，请清理数据'
		}
		
		let message = '系统异常，请稍后重试'
		
		// 匹配友好错误信息
		for (const [key, value] of Object.entries(friendlyMessages)) {
			if (errorInfo.message.includes(key)) {
				message = value
				break
			}
		}
		
		try {
			uni.showToast({
				title: message,
				icon: 'none',
				duration: 3000
			})
		} catch (error) {
			console.error('Failed to show error toast:', error)
		}
	}
	
	onError(callback) {
		this.errorCallbacks.push(callback)
	}
	
	reportError(error, context = 'Manual Report') {
		this.handleError(error, context)
	}
}

// 创建实例
export const logger = new MiniprogramLogger()
export const errorHandler = new MiniprogramErrorHandler()

// 异步操作包装器
export function asyncWrapper(asyncFn, context = 'Async Operation') {
	return async (...args) => {
		try {
			logger.debug(`Starting ${context}`, { args })
			const result = await asyncFn(...args)
			logger.debug(`Completed ${context}`, { result })
			return result
		} catch (error) {
			errorHandler.reportError(error, context)
			throw error
		}
	}
}

// 重试机制
export async function retryAsync(asyncFn, maxRetries = 3, delay = 1000) {
	let lastError
	
	for (let i = 0; i < maxRetries; i++) {
		try {
			return await asyncFn()
		} catch (error) {
			lastError = error
			logger.warn(`Retry attempt ${i + 1}/${maxRetries} failed`, error)
			
			if (i < maxRetries - 1) {
				await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, i)))
			}
		}
	}
	
	throw lastError
}

// 表单验证错误处理
export function handleValidationError(errors) {
	const errorMessages = []
	
	Object.entries(errors).forEach(([field, error]) => {
		if (Array.isArray(error)) {
			errorMessages.push(...error)
		} else {
			errorMessages.push(error)
		}
	})
	
	const message = errorMessages.join('；')
	
	try {
		uni.showToast({
			title: message,
			icon: 'none',
			duration: 3000
		})
	} catch (error) {
		console.error('Failed to show validation error:', error)
	}
	
	logger.warn('Validation Error', { errors, message })
}

// 业务逻辑错误处理
export function handleBusinessError(error) {
	const businessErrors = {
		'EXAM_NOT_FOUND': '考试不存在',
		'EXAM_EXPIRED': '考试已过期',
		'EXAM_COMPLETED': '考试已完成',
		'INSUFFICIENT_PERMISSION': '权限不足',
		'DATA_NOT_FOUND': '数据不存在',
		'OPERATION_FAILED': '操作失败'
	}
	
	const message = businessErrors[error.code] || error.message || '操作失败'
	
	try {
		uni.showModal({
			title: '提示',
			content: message,
			showCancel: false
		})
	} catch (modalError) {
		console.error('Failed to show business error modal:', modalError)
	}
	
	logger.warn('Business Error', error)
}
